<!doctype html>
<html lang="en-us">
<head>

    <meta charset="utf-8">
    <meta name="generator" content="Hugo 0.59.1" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>SpringSecurity中formLogin登录认证模式 | 林贤钦</title>
    <meta property="og:title" content="SpringSecurity中formLogin登录认证模式 - 林贤钦">
    <meta property="og:type" content="article">
        
    <meta property="article:published_time" content="2020-03-16T03:31:19&#43;08:00">
        
        
    <meta property="article:modified_time" content="2020-03-16T03:31:19&#43;08:00">
        
    <meta name="Keywords" content="java,博客,项目管理,软件架构,公众号,小程序">
    <meta name="description" content="SpringSecurity中formLogin登录认证模式">
        
    <meta name="author" content="林贤钦">
    <meta property="og:url" content="http://linxianqin.gitee.io/post/springSecurity%E4%B8%ADformLogin%E7%99%BB%E5%BD%95%E8%AE%A4%E8%AF%81%E6%A8%A1%E5%BC%8F/">
    <link rel="shortcut icon" href="/img/favicon.ico" type="image/x-icon">

    <link rel="stylesheet" href="/css/normalize.css">
    
        <link rel="stylesheet" href="/css/prism.css">
    
    <link rel="stylesheet" href="/css/style.css">
    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

    


    
    
</head>

<body>
<header id="header" class="clearfix">
	<div class="container">
        <div class="col-group">
            <div class="site-name ">
                
                    <a id="logo" href="http://linxianqin.gitee.io">
                        林贤钦
                    </a>
                
                <p class="description">专注于Java、微信小程序、移动互联网、项目管理、软件架构</p>
            </div>
            <div>
                <nav id="nav-menu" class="clearfix">
                    <a class="current" href="http://linxianqin.gitee.io">首页</a>
                    
                    <a  href="http://linxianqin.gitee.io/archives/" title="归档">归档</a>
                    
                    <a  href="http://linxianqin.gitee.io/about/" title="关于">关于</a>
                    
                </nav>
            </div>
        </div>
    </div>
</header>


<div id="body">
        
        
    <div class="container">
        <div class="col-group">

            <div class="col-8" id="main">
                <div class="res-cons">
                    <article class="post">
                        <header>
                            <h1 class="post-title">SpringSecurity中formLogin登录认证模式</h1>
                        </header>
                        <date class="post-meta meta-date">
                            2020年3月16日
                        </date>
                        
                        <div class="post-meta">
                            <span>|</span>
                            
                                <span class="meta-category"><a href="http://linxianqin.gitee.io/categories/springSecurity">springSecurity</a></span>
                            
                        </div>
                        
                        
                        <div class="post-meta">
                            <span id="busuanzi_container_page_pv">|<span id="busuanzi_value_page_pv"></span><span> 阅读</span></span>
                        </div>
                        
                        
                        <div class="post-content">
							<nav id="TableOfContents">
<ul>
<li>
<ul>
<li><a href="#一-formlogin的应用场景">一、formLogin的应用场景</a>
<ul>
<li><a href="#准备工作">准备工作</a></li>
<li><a href="#需求">需求</a></li>
</ul></li>
<li><a href="#二-说明">二、说明</a></li>
<li><a href="#三-实现formlogin模式基础配置">三、实现formLogin模式基础配置</a></li>
<li><a href="#四-实现资源访问限制的需求">四、实现资源访问限制的需求</a></li>
</ul></li>
</ul>
</nav>
                            

<h2 id="一-formlogin的应用场景">一、formLogin的应用场景</h2>

<p>Spring Security的HttpBasic模式比较简单，只是进行了通过携带Http的Header进行简单的登录验证，而且没有定制的登录页面，所以使用场景比较窄,并且容易被破解。
对于一个完整的应用系统，与登录验证相关的页面都是高度定制化的，非常美观而且提供多种登录方式。这就需要Spring Security支持我们自己定制登录页面，也就是本文给大家介绍的formLogin模式登录认证模式。</p>

<h3 id="准备工作">准备工作</h3>

<ul>
<li>新建一个Spring Boot 的web应用，引入Spring Security Starter。</li>
<li>准备一个login.html登录页面，页面内容非常简单，一个from表单、用户名和密码输入框，一个提交按钮</li>
<li>准备一个首页index.html，在登录成功之后需要进入index.html首页</li>
<li>首页可以看到syslog（日志管理）、sysuer（用户管理）、biz1（业务一）、biz2（业务二）四个页面超文本链接选项。通过controller控制层跳转页面，并在对应页面写一些标志性文字即可，不需写具体业务。</li>
</ul>

<h3 id="需求">需求</h3>

<ul>
<li>我们希望biz1（业务一）、biz2（业务二）普通的操作用户user就可以访问</li>
<li>我们希望管理员可以访问包括syslog（日志管理）和sysuser(用户管理)在内的所有资源</li>
</ul>

<p>以上就是本文介绍formLogin模式需要进行的准备工作及需求，下面我们就来实现其中的核心的登录验证逻辑，准备工作非常简单请自行实现。（新建spring boot应用，登录页面、首页、四个业务页面都写成非常简单的html即可，不用写实际业务和样式。）</p>

<h2 id="二-说明">二、说明</h2>

<p>formLogin模式的三要素：</p>

<ul>
<li>登录验证逻辑</li>
<li>资源访问控制规则，如：资源权限、角色权限</li>
<li>用户信息</li>
</ul>

<p>一般来说，使用权限认证框架的的业务系统登录验证逻辑是固定的，而资源访问控制规则和用户信息是从数据库或其他存储介质灵活加载的。但本文所有的用户、资源、权限信息都是代码配置写死的，旨在为大家介绍formLogin认证模式，如何从数据库加载权限认证相关信息我还会结合RBAC权限模型再写文章的。</p>

<h2 id="三-实现formlogin模式基础配置">三、实现formLogin模式基础配置</h2>

<p>首先，我们要继承WebSecurityConfigurerAdapter ，重写configure(HttpSecurity http) 方法，该方法用来配置登录验证逻辑。请注意看下文代码中的注释信息。</p>

<pre><code class="language-java">@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .formLogin()
                .loginPage(&quot;/login.html&quot;)//登录页面
                .loginProcessingUrl(&quot;/login&quot;)//登录认证处理
                .defaultSuccessUrl(&quot;/index&quot;)//默认登录成功页面
                .and()
                .authorizeRequests()
                .antMatchers(&quot;/login.html&quot;,&quot;/login&quot;).permitAll()//开放，不需要登录认证即可访问
                .antMatchers(&quot;/biz1&quot;,&quot;/biz2&quot;)//需要对外暴露的资源路径
                    .hasAnyAuthority(&quot;ROLE_user&quot;,&quot;ROLE_admin&quot;)//user角色和admin角色可以访问
                .antMatchers(&quot;/syslog&quot;,&quot;/sysuser&quot;)
                    .hasRole(&quot;admin&quot;)//admin角色可以访问
                .anyRequest().authenticated();
    }
}
</code></pre>

<p>上面的代码分为两部分：</p>

<ul>
<li>第一部分是formLogin配置段，用于配置登录验证逻辑相关的信息。如：登录页面、登录成功页面、登录请求处理路径等。</li>
<li>第二部分是authorizeRequests配置端，用于配置资源的访问权限。如：开发登录页面的permitAll开放访问，“/biz1”（业务一页面资源）需要有资源ID为&rdquo;biz1&rdquo;的用户才可以访问。</li>
</ul>

<p>这时候，我们通过浏览器访问，随便测试一个没有访问权限的资源，都会跳转到login.html页面。</p>

<h2 id="四-实现资源访问限制的需求">四、实现资源访问限制的需求</h2>

<p>在上文中，我们配置了登录验证及资源访问的权限规则，我们还没有具体的用户，下面我们就来配置具体的用户。重写WebSecurityConfigurerAdapter的 configure(AuthenticationManagerBuilder auth)方法</p>

<pre><code class="language-java"> @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.inMemoryAuthentication()
                .withUser(&quot;user&quot;)
                .password(passwordEncoder().encode(&quot;123456&quot;))
                .roles(&quot;user&quot;)
                    .and()
                .withUser(&quot;admin&quot;)
                .password(passwordEncoder().encode(&quot;123456&quot;))
                .roles(&quot;admin&quot;)
                    .and()
                .passwordEncoder(passwordEncoder());
    }
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
</code></pre>

<ul>
<li><p><code>inMemoryAuthentication</code>指的是在内存里面存储用户的身份认证和授权信息。</p></li>

<li><p><code>withUser(&quot;user&quot;)</code>用户名是user</p></li>

<li><p><code>password(passwordEncoder().encode(&quot;123456&quot;))</code>密码是加密之前的123456</p></li>

<li><p><code>authorities(&quot;biz1&quot;,&quot;biz2&quot;)</code>指的是user用户拥有资源ID为biz1(业务一)和biz2(业务二)资源的权限</p></li>
</ul>

<p>这样，我们就实现了文首提出的普通用户只能访问biz1(业务一)和biz2(业务二)资源的需求。那么管理员用户可以访问所有的资源的配置方式</p>

<p>## 五、静态资源访问</p>

<p>在我们的实际开发中，登录页面login.html和控制层Controller登录验证&rsquo;/login&rsquo;都必须无条件的开放。除此之外，一些静态资源如css、js文件通常也都不需要验证权限，我们需要将它们的访问权限也开放出来。下面就是实现的方法：重写WebSecurityConfigurerAdapter类的configure(WebSecurity web) 方法</p>

<pre><code class="language-java">  @Override
  public void configure(WebSecurity web) {
       //将项目中静态资源路径开放出来
       web.ignoring()
          .antMatchers( &quot;/css/**&quot;, &quot;/fonts/**&quot;, &quot;/img/**&quot;, &quot;/js/**&quot;);
  }
</code></pre>

                        </div>
						 
                        
<div class="post-archive">
    <ul class="post-copyright">
        <li><strong>原文作者：</strong><a rel="author" href="http://linxianqin.gitee.io">林贤钦</a></li>
        <li style="word-break:break-all"><strong>原文链接：</strong><a href="http://linxianqin.gitee.io/post/springSecurity%E4%B8%ADformLogin%E7%99%BB%E5%BD%95%E8%AE%A4%E8%AF%81%E6%A8%A1%E5%BC%8F/">http://linxianqin.gitee.io/post/springSecurity%E4%B8%ADformLogin%E7%99%BB%E5%BD%95%E8%AE%A4%E8%AF%81%E6%A8%A1%E5%BC%8F/</a></li>
        <li><strong>版权声明：</strong>本作品采用<a rel="license" href="https://linxianqin.gitee.io">知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议</a>进行许可，非商业转载请注明出处（作者，原文链接），商业转载请联系作者获得授权。</li>
    </ul>
</div>
<br/>



                        

<div class="post-archive">
    <h2>See Also</h2>
    <ul class="listing">
        
        <li><a href="/post/java8%E6%96%B0%E7%89%B9%E6%80%A7Lambda%E8%A1%A8%E8%BE%BE%E5%BC%8F/">Java8新特性Lambda表达式</a></li>
        
        <li><a href="/post/java8%E6%96%B0%E7%89%B9%E6%80%A7stream%E6%B5%81/">Java8新特性stream流</a></li>
        
        <li><a href="/post/yml%E6%96%87%E4%BB%B6%E7%9A%84%E7%AE%80%E4%BB%8B/">Yml文件的简介</a></li>
        
        <li><a href="/post/json%E4%B8%8Ejava%E6%A0%BC%E5%BC%8F%E7%9B%B8%E4%BA%92%E8%BD%AC%E5%8C%96/">json与java格式相互转化</a></li>
        
        <li><a href="/post/%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95%E8%80%83%E8%AF%95%E6%9C%9F%E6%9C%AB%E5%A4%8D%E4%B9%A0/">软件测试考试期末复习</a></li>
        
    </ul>
</div>


                        <div class="post-meta meta-tags">
                            
                            <ul class="clearfix">
                                
                                <li><a href="http://linxianqin.gitee.io/tags/spring">spring</a></li>
                                
                                <li><a href="http://linxianqin.gitee.io/tags/java">java</a></li>
                                
                            </ul>
                            
                        </div>
                    </article>
                    
    

    
    
    <div class="post bg-white">
      <script src="https://utteranc.es/client.js"
            repo= "757610938/hugo-blogs-utterances"
            issue-term="pathname"
            theme="github-light"
            crossorigin="anonymous"
            async>
      </script>
    </div>
    
                </div>
            </div>
            <div id="secondary">
    <section class="widget">
        <form id="search" action="//www.google.com/search" method="get" accept-charset="utf-8" target="_blank" _lpchecked="1">
      
      <input type="text" name="q" maxlength="20" placeholder="Search">
      <input type="hidden" name="sitesearch" value="http://linxianqin.gitee.io">
      <button type="submit" class="submit icon-search"></button>
</form>
    </section>
    
    <section class="widget">
        <h3 class="widget-title">最近文章</h3>
<ul class="widget-list">
    
    <li>
        <a href="http://linxianqin.gitee.io/post/java-%E5%8F%8D%E5%B0%84/" title="Java 反射">Java 反射</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/java-%E9%93%BE%E8%A1%A8/" title="Java 链表">Java 链表</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/%E7%9F%AD%E4%BF%A1%E6%B3%A8%E5%86%8C%E5%92%8C%E5%BE%AE%E4%BF%A1%E7%99%BB%E5%BD%95%E7%9A%84%E5%AE%9E%E7%8E%B0/" title="短信注册和微信登录的实现">短信注册和微信登录的实现</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/OAuth2.0%E8%AE%A4%E8%AF%81%E6%8E%88%E6%9D%83%E5%8D%95%E7%82%B9%E7%99%BB%E5%BD%95/" title="OAuth2.0认证授权单点登录">OAuth2.0认证授权单点登录</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/Nacos%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83/" title="Nacos服务注册中心">Nacos服务注册中心</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/SpringCloud%E5%BE%AE%E6%9C%8D%E5%8A%A1/" title="SpringCloud微服务">SpringCloud微服务</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/%E9%98%BF%E9%87%8C%E4%BA%91%E8%A7%86%E9%A2%91%E7%82%B9%E6%92%AD%E6%9C%8D%E5%8A%A1/" title="阿里云视频点播服务前后端实现">阿里云视频点播服务前后端实现</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/%E9%98%9F%E5%88%97/" title="队列">队列</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/%E7%A8%80%E7%96%8F%E6%95%B0%E7%BB%84/" title="稀疏数组">稀疏数组</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/%E9%98%BF%E9%87%8C%E4%BA%91EasyExcel%E5%AE%9E%E7%8E%B0%E5%90%8E%E7%AB%AF%E5%AF%B9Excel%E7%9A%84%E8%AF%BB%E5%86%99%E6%93%8D%E4%BD%9C/" title="使用阿里云EasyExcel实现后端对Excel的读写操作">使用阿里云EasyExcel实现后端对Excel的读写操作</a>
    </li>
    
</ul>
    </section>

    

    <section class="widget">
        <h3 class="widget-title">分类</h3>
<ul class="widget-list">
    
    <li><a href="http://linxianqin.gitee.io/categories/JWT/">JWT (2)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/hugo/">hugo (2)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/java/">java (18)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/java8/">java8 (1)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/springCloud/">springCloud (2)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/springSecurity/">springSecurity (4)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/vue/">vue (5)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/yml/">yml (1)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/">数据结构 (3)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/">软件测试 (1)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/%E9%98%BF%E9%87%8C%E4%BA%91/">阿里云 (4)</a></li>
    
</ul>
    </section>

    <section class="widget">
        <h3 class="widget-title">标签</h3>
<div class="tagcloud">
    
    <a href="http://linxianqin.gitee.io/tags/JWT/">JWT</a>
    
    <a href="http://linxianqin.gitee.io/tags/hugo/">hugo</a>
    
    <a href="http://linxianqin.gitee.io/tags/java/">java</a>
    
    <a href="http://linxianqin.gitee.io/tags/java8/">java8</a>
    
    <a href="http://linxianqin.gitee.io/tags/spring/">spring</a>
    
    <a href="http://linxianqin.gitee.io/tags/springBoot/">springBoot</a>
    
    <a href="http://linxianqin.gitee.io/tags/springCloud/">springCloud</a>
    
    <a href="http://linxianqin.gitee.io/tags/ssm/">ssm</a>
    
    <a href="http://linxianqin.gitee.io/tags/vue/">vue</a>
    
    <a href="http://linxianqin.gitee.io/tags/yml/">yml</a>
    
    <a href="http://linxianqin.gitee.io/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/">数据结构</a>
    
    <a href="http://linxianqin.gitee.io/tags/%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/">软件测试</a>
    
    <a href="http://linxianqin.gitee.io/tags/%E9%98%BF%E9%87%8C%E4%BA%91/">阿里云</a>
    
</div>
    </section>

    
<section class="widget">
    <h3 class="widget-title">友情链接</h3>
    <ul class="widget-list">
        
        <li>
            <a target="_blank" href="https://www.cnki.net" title="中国知网">中国知网</a>
        </li>
        
        <li>
            <a target="_blank" href="https://linxianqin.com" title="个人的另一个博客网站(国内加载慢)">个人的另一个博客网站(国内加载慢)</a>
        </li>
        
    </ul>
</section>


    <section class="widget">
        <h3 class="widget-title">其它</h3>
        <ul class="widget-list">
            <li><a href="http://linxianqin.gitee.io/index.xml">文章 RSS</a></li>
        </ul>
    </section>
</div>
        </div>
    </div>
</div>
<footer id="footer">
    <div class="container">
        &copy; 2020 <a href="http://linxianqin.gitee.io">林贤钦 By 林贤钦</a>.
        Powered by <a rel="nofollow noreferer noopener" href="https://gohugo.io" target="_blank">Hugo</a>.
        <a href="https://www.flysnow.org/" target="_blank">Theme</a> based on <a href="https://github.com/rujews/maupassant-hugo" target="_blank">maupassant</a>.
        
    </div>
</footer>


    
    <script type="text/javascript">
        
        (function () {
            $("pre code").parent().addClass("line-numbers")
        }());

        window.MathJax = {
            tex2jax: {
                inlineMath: [['$', '$']],
                processEscapes: true
                }
            };
    </script>
    <script type="text/javascript" src="/js/prism.js" async="true"></script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML' async></script>


<a id="rocket" href="#top"></a>
<script type="text/javascript" src="/js/totop.js?v=0.0.0" async=""></script>

<script type="application/javascript">
var doNotTrack = false;
if (!doNotTrack) {
	window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
	ga('create', 'GA ID', 'auto');
	
	ga('send', 'pageview');
}
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>



    <script type="text/javascript" src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" async></script>




</body>
</html>
